using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class MobSpawnController : MonoBehaviour
{
	public static MobSpawnController instance;

	public int aggressiveMobsCount;

	public float externalRingRadius;

	public float internalRingRadius;

	public int percentPointInFrontOfPlayer = 60;

	public float angleBetwenVectors = 45f;

	public float timeBetwenDeadAndSpawnAggressiveMobs = 40f;

	public float timeToFirsAgr = 60f;

	public float secondsForNextIteration;

	public int maxIterationCount;

	public LayerMask collisionGround;

	public List<MobPoint> pointsInFrontOfPlayer;

	public List<MobPoint> pointsBehindPlayer;

	public List<EnemyBehavior> MobsList;

	public SectorMobManager[] allMobsSectors;

	private bool allEnemiesAggressive;

	private Vector3 spawnPoint;

	private EnemyBehavior enemyBehaviour;

	private int mobLevel;

	private bool autoSpawn = true;

	private bool distanceRemoveMobs = true;

	private bool pointReady;

	public bool canSpawnAggressiveMobs = true;

	public bool globalAgrState;

	private List<MobPoint> spPoint = new List<MobPoint>();

	private void Awake()
	{
		instance = this;
	}

	public void Init()
	{
		StartCoroutine(InitCoroutine());
	}

	private IEnumerator InitCoroutine()
	{
		while (ManagerPreloadingSectors.thisScript.isFirstLoading)
		{
			yield return null;
		}
		yield return new WaitForSeconds(3f);
		PoolManager.instance.InitBaseOnMod();
		base.enabled = settings.offlineMode;
		if (!settings.offlineMode || !SceneManager.GetActiveScene().name.Equals("Level1"))
		{
			StopCoroutine(FindPointsNearPlayer());
			StopCoroutine(RespawnPointFinder());
			StopCoroutine(InstantiateMobs());
			StopCoroutine(FollowManager());
			StopCoroutine(RemoveMobs());
			StopAllCoroutines();
			MobsList.Clear();
			PlayerBehavior.OnDead -= OnPlayerDead;
			globalAgrState = false;
		}
		else
		{
			PlayerBehavior.OnDead += OnPlayerDead;
			while (ManagerPreloadingSectors.thisScript.isFirstLoading)
			{
				yield return null;
			}
			if (allMobsSectors.Length == 0)
			{
			}
			allMobsSectors = Object.FindObjectsOfType<SectorMobManager>();
			if (MobTypesManager.instance != null)
			{
				MobTypesManager.instance.InitSectors();
			}
			canSpawnAggressiveMobs = false;
			Invoke("StartSpawnAggressiveMobs", timeToFirsAgr);
			StartCoroutine(RespawnPointFinder());
			StartCoroutine(InstantiateMobs());
			StartCoroutine(RemoveMobs());
		}
		if (!settings.learningCompleted)
		{
			autoSpawn = false;
			distanceRemoveMobs = false;
			StartCoroutine(RemoveMobs());
		}
		yield return null;
	}

	private void OnDestroy()
	{
		instance = null;
		PlayerBehavior.OnDead -= OnPlayerDead;
	}

	private void Start()
	{
		Init();
	}

	public void DestroyMob()
	{
	}

	public void CashMobSpawn()
	{
		SectorMobManager[] array = Object.FindObjectsOfType<SectorMobManager>();
		SectorMobManager[] array2 = array;
		foreach (SectorMobManager sectorMobManager in array2)
		{
			sectorMobManager.CashSectorMob();
		}
	}

	private IEnumerator RemoveMobs()
	{
		while (true)
		{
			if (!Application.isLoadingLevel)
			{
				globalAgrState = false;
				GameTopWindow.instance.ToggleAggressiveLabel();
				for (int i = 0; i < MobsList.Count; i++)
				{
					if (MobsList[i].currentState == EnemyState.Aggressive || MobsList[i].currentState == EnemyState.Chasing)
					{
						globalAgrState = true;
						GameTopWindow.instance.ToggleAggressiveLabel();
					}
					if (MobsList[i].waitRespawn)
					{
						if (MobsList[i].behaviorModel == BehaviorModel.Aggressive)
						{
							aggressiveMobsCount--;
							GameTopWindow.instance.ToggleAggressiveLabel();
						}
						PoolManager.instance.ReturnToPool(MobsList[i].poolName, MobsList[i].gameObject);
						yield return null;
						MobsList.RemoveAt(i);
						i--;
					}
					else if (distanceRemoveMobs && settings.learningCompleted && Vector3.Distance(GameController.instance.playerScript.transform.position, MobsList[i].transform.position) > externalRingRadius)
					{
						if (MobsList[i].behaviorModel == BehaviorModel.Aggressive)
						{
							aggressiveMobsCount--;
							GameTopWindow.instance.ToggleAggressiveLabel();
						}
						PoolManager.instance.ReturnToPool(MobsList[i].poolName, MobsList[i].gameObject);
						MobsList.RemoveAt(i);
						i--;
						yield return null;
					}
				}
			}
			yield return new WaitForSeconds(1f);
		}
	}

	private IEnumerator FollowManager()
	{
		while (true)
		{
			if (!Application.isLoadingLevel)
			{
				for (int i = 0; i < MobsList.Count; i++)
				{
					if (MobsList[i] != null)
					{
					}
				}
			}
			yield return new WaitForEndOfFrame();
		}
	}

	private IEnumerator InstantiateMobs()
	{
		MobPoint point = new MobPoint();
		SectorMobManager sectorMobManager2 = null;
		int counter = 0;
		while (autoSpawn)
		{
			if (MobsList.Count < settings.maxKolVragov)
			{
				point = FindPointForSpawn();
				if (point != null)
				{
					sectorMobManager2 = point.sector;
					if (sectorMobManager2.mobGroups.Count > 0)
					{
						yield return StartCoroutine(MobSpawner(point, sectorMobManager2.mobGroups[sectorMobManager2.GetMobGroupNumber()].group, sectorMobManager2));
					}
				}
			}
			do
			{
				counter++;
				yield return new WaitForSeconds(0.2f);
			}
			while (Application.isLoadingLevel && counter < 11);
			counter = 0;
		}
	}

	private IEnumerator MobSpawner(MobPoint point, MobGroup group, SectorMobManager sector)
	{
		if (!settings.offlineMode)
		{
			yield break;
		}
		if (group.singleSpawn)
		{
			SingleMobSpawn(group.GetSingleMob(), point, sector);
		}
		else
		{
			for (int i = 0; i < group.enemies.Count; i++)
			{
				SingleMobSpawn(group.enemies[i].mob, point, sector);
				yield return new WaitForSeconds(0.1f);
			}
		}
		yield return null;
	}

	public void ForceSpawnSingleMob(MobGroup needGroup, SectorMobManager needSector)
	{
		if (needGroup != null && needSector != null)
		{
			StartCoroutine(MobSpawner(null, needGroup, needSector));
		}
	}

	public EnemyBehavior SingleMobSpawn(MobParameters element, MobPoint point = null, SectorMobManager sector = null, bool randomPosition = true)
	{
		if (element != null && PoolManager.instance != null)
		{
			if (point == null && sector != null)
			{
				point = FindPointInSector(sector);
			}
			if (point == null)
			{
				return null;
			}
			if (sector == null)
			{
				SectorMobManager sector2 = point.sector;
			}
			if (randomPosition)
			{
				spawnPoint.x = point.position.x + Random.Range(-0.5f, 0.5f);
				spawnPoint.y = point.position.y + 1f;
				spawnPoint.z = point.position.z + Random.Range(-0.5f, 0.5f);
			}
			else
			{
				spawnPoint = point.position;
			}
			mobLevel = 0;
			for (int i = 0; i < element.levelsList.Count; i++)
			{
				if (element.levelsList[i].StartLevel <= CupsManager.CurrentTier + 1 && element.levelsList[i].StartLevel > element.levelsList[mobLevel].StartLevel)
				{
					mobLevel = i;
				}
			}
			RaycastHit hitInfo;
			if (Physics.Raycast(spawnPoint, Vector3.down, out hitInfo, 2f, collisionGround))
			{
				spawnPoint = hitInfo.point;
				GameObject gameObject = PoolManager.instance.TakeFromPool(element.poolName, base.transform);
				if (gameObject != null)
				{
					enemyBehaviour = gameObject.GetComponent<EnemyBehavior>();
					enemyBehaviour.canMove = true;
					MobsList.Add(enemyBehaviour);
					distanceRemoveMobs = false;
					enemyBehaviour.AddEventListener(this, "MobPlased", delegate
					{
						distanceRemoveMobs = true;
					}, true);
					if (allEnemiesAggressive)
					{
						enemyBehaviour.behaviorModel = BehaviorModel.Aggressive;
					}
					else
					{
						enemyBehaviour.behaviorModel = element.behaviorModel;
					}
					enemyBehaviour.gameObject.SetActive(true);
					enemyBehaviour.MobSpawned(spawnPoint, Quaternion.Euler(point.rotation), element, mobLevel, sector);
					if (enemyBehaviour.behaviorModel == BehaviorModel.Aggressive)
					{
						aggressiveMobsCount++;
						GameTopWindow.instance.ToggleAggressiveLabel();
					}
					return enemyBehaviour;
				}
			}
		}
		return null;
	}

	public void SetAllMobsAggressive(bool val)
	{
		allEnemiesAggressive = val;
		foreach (EnemyBehavior mobs in MobsList)
		{
			PoolManager.instance.ReturnToPool(mobs.poolName, mobs.gameObject);
		}
		MobsList.Clear();
	}

	private IEnumerator RespawnPointFinder()
	{
		while (true)
		{
			yield return StartCoroutine(FindPointsNearPlayer());
			yield return new WaitForSeconds(secondsForNextIteration);
		}
	}

	private IEnumerator FindPointsNearPlayer()
	{
		pointsBehindPlayer.Clear();
		pointsInFrontOfPlayer.Clear();
		pointReady = false;
		int counter = 0;
		MobPoint mobPoint3 = new MobPoint();
		if (allMobsSectors != null)
		{
			for (int sector = 0; sector < allMobsSectors.Length; sector++)
			{
				if (!GameController.instance || !GameController.instance.playerScript || !(Vector3.Distance(GameController.instance.playerScript.transform.position, allMobsSectors[sector].centerPoint) - allMobsSectors[sector].sectorRadius < externalRingRadius))
				{
					continue;
				}
				for (int point = 0; point < allMobsSectors[sector].sectorPoints.Length; point++)
				{
					if (GameController.instance == null || GameController.instance == null || GameController.instance.playerScript == null)
					{
						continue;
					}
					float angle = Vector3.Angle(GameController.instance.cameraGame.transform.forward, allMobsSectors[sector].sectorPoints[point] - GameController.instance.playerScript.transform.position);
					if (angle <= angleBetwenVectors)
					{
						if (Vector3.Distance(allMobsSectors[sector].sectorPoints[point], GameController.instance.playerScript.transform.position) > internalRingRadius)
						{
							mobPoint3 = new MobPoint
							{
								position = allMobsSectors[sector].sectorPoints[point],
								sector = allMobsSectors[sector]
							};
							pointsInFrontOfPlayer.Add(mobPoint3);
						}
					}
					else if (Vector3.Distance(allMobsSectors[sector].sectorPoints[point], GameController.instance.playerScript.transform.position) < internalRingRadius)
					{
						mobPoint3 = new MobPoint
						{
							position = allMobsSectors[sector].sectorPoints[point],
							sector = allMobsSectors[sector]
						};
						pointsBehindPlayer.Add(mobPoint3);
					}
					counter++;
					if (counter > maxIterationCount)
					{
						counter = 0;
						yield return null;
					}
				}
			}
		}
		pointReady = true;
		yield return null;
	}

	private MobPoint FindPointInSector(SectorMobManager sector)
	{
		spPoint.Clear();
		if (!pointReady)
		{
			return null;
		}
		if (sector != null)
		{
			for (int i = 0; i < pointsInFrontOfPlayer.Count; i++)
			{
				if (pointsInFrontOfPlayer[i].sector == sector)
				{
					spPoint.Add(pointsInFrontOfPlayer[i]);
				}
			}
			for (int j = 0; j < pointsBehindPlayer.Count; j++)
			{
				if (pointsBehindPlayer[j].sector == sector)
				{
					spPoint.Add(pointsBehindPlayer[j]);
				}
			}
		}
		if (spPoint.Count > 0)
		{
			return spPoint[Random.Range(0, spPoint.Count)];
		}
		return FindPointForSpawn();
	}

	private MobPoint FindPointForSpawn()
	{
		if ((pointsBehindPlayer.Count == 0 && pointsInFrontOfPlayer.Count == 0) || !pointReady)
		{
			return null;
		}
		int num = Random.Range(1, 100);
		if (num <= percentPointInFrontOfPlayer && pointsInFrontOfPlayer.Count > 0)
		{
			return pointsInFrontOfPlayer[Random.Range(0, pointsInFrontOfPlayer.Count)];
		}
		if (pointsBehindPlayer.Count > 0)
		{
			return pointsBehindPlayer[Random.Range(0, pointsBehindPlayer.Count)];
		}
		return null;
	}

	public void OnPlayerDead()
	{
		if (settings.offlineMode)
		{
			canSpawnAggressiveMobs = false;
			for (int i = 0; i < MobsList.Count; i++)
			{
				MobsList[i].CheckPlayerDeath();
			}
			Invoke("StartSpawnAggressiveMobs", timeBetwenDeadAndSpawnAggressiveMobs);
		}
	}

	public void StartSpawnAggressiveMobs()
	{
		CancelInvoke();
		canSpawnAggressiveMobs = true;
	}

	private int GetRandomSkinNumber(MobParameters element)
	{
		return element.skinList[Random.Range(0, element.skinList.Count)].skinNumbers;
	}
}
